package com.example.multinetty.netty.firstprotocal;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.stream.ChunkedWriteHandler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class NettyServer implements ApplicationRunner {
	
	@Autowired
	private ServletNettyHandler servletNettyHandler;

	@Override
	public void run(ApplicationArguments args) throws Exception {

		//如果是多个不同的协议，应让它对应不同的端口。如果同一个端口绑定不同的协议，必然会存在SocketChannel的缓存公用。这个时候会出现粘包，混包的出现
		//不同的端口起不同的协议，那么就在一个进程中启动不同的服务器实例，每个服务类实例绑定不同的端口，我感觉就应该可以实现单进程的多协议的服务器了。
		// 服务类
		ServerBootstrap b = new ServerBootstrap();

		// 创建boss和worker
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup = new NioEventLoopGroup();

		try {
			// 设置循环线程组事例
			b.group(bossGroup, workerGroup);

			// 设置channel工厂
			b.channel(NioServerSocketChannel.class);

			// 设置管道
			b.childHandler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch) throws Exception {

					//根据ch17章中的内容，定义了这几个参数。这个长度，仅仅是消息体的长度。
					/*ch.pipeline().addLast(new RequestDecoderExtLenField(1024*1024,8,4));
					ch.pipeline().addLast(new ResponseEncoder());
					ch.pipeline().addLast(new ServerHandler());*/
					ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,
							0, 4, 0, 4));
					ch.pipeline().addLast(new ByteToFullRequestDecoder());
					// 把接收到的Bytebuf数据包转换成String
					//pipeline.addLast(new StringDecoder());

		/*pipeline.addLast("decoder", new HttpRequestDecoder());
		pipeline.addLast("aggregator", new HttpObjectAggregator(65536));*/
					ch.pipeline().addLast(new LengthFieldPrepender(4, false));
					ch.pipeline().addLast(new FullHttpResponseToStringEncoder());
					//	pipeline.addLast("encoder", new HttpResponseEncoder());
					ch.pipeline().addLast("chunkedWriter", new ChunkedWriteHandler());
					//传递的参数为 FullHttpRequest
					ch.pipeline().addLast("handler", servletNettyHandler);
				}
			});

			b.option(ChannelOption.SO_BACKLOG, 2048);// 链接缓冲池队列大小

			// 绑定端口
			b.bind(8086).sync();

			System.out.println("start2!!!");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
